package api

import (
	"encoding/csv"
	"fmt"
	"net/http"
	"pids-cloud-server/app/common"
	"pids-cloud-server/app/middleware"
	"pids-cloud-server/entity"
	"pids-cloud-server/logging"
	"pids-cloud-server/utils"
	"strconv"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

// GetModelOidList 获取ModelOID信息列表
// @Summary 获取ModelOID信息列表
// @Description 获取ModelOID信息列表,支持按Model筛选
// @Tags ModelOID管理
// @Accept json
// @Produce json
// @Param page query int false "页码，默认1"
// @Param pageSize query int false "每页大小，默认10"
// @Param model query string false "设备型号"
// @Success 200 {object} common.Result{data=common.PageResult{list=[]entity.ModelOid}} "成功"
// @Failure 500 {object} common.Result "失败"
// @Router /modeloid/list [get]
func GetModelOidList(c *gin.Context) {
	// 从上下文中获取分页参数
	pagination, _ := c.Get("pagination")
	paging := pagination.(*middleware.PaginationParams)

	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	// 获取查询参数
	model := c.Query("model")

	// 构建查询条件
	query := db.Model(&entity.ModelOid{})
	if model != "" {
		query = query.Where("model LIKE ?", "%"+model+"%")
	}

	// 获取总记录数
	var total int64
	if err := query.Count(&total).Error; err != nil {
		common.ErrorResponse(c, 500, "查询失败")
		return
	}

	// 获取分页数据
	var modelOidList []entity.ModelOid
	if err := query.Offset((paging.Page - 1) * paging.PageSize).Limit(paging.PageSize).Find(&modelOidList).Error; err != nil {
		common.ErrorResponse(c, 500, "查询失败")
		return
	}

	common.SuccessPageResponse(c, modelOidList, total, paging.Page, paging.PageSize)
}

// AddModelOid 新增ModelOID信息
// @Summary 新增ModelOID信息
// @Description 新增一条ModelOID信息
// @Tags ModelOID管理
// @Accept json
// @Produce json
// @Param modelOid body entity.ModelOid true "ModelOID信息"
// @Success 200 {object} common.Result{data=entity.ModelOid} "成功"
// @Failure 400 {object} common.Result "参数错误"
// @Failure 500 {object} common.Result "新增失败"
// @Router /api/modeloid/add [post]
func AddModelOid(c *gin.Context) {
	var modelOid entity.ModelOid
	if err := c.ShouldBindJSON(&modelOid); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "参数错误",
			"data":    nil,
		})
		return
	}

	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	if err := db.Create(&modelOid).Error; err != nil {
		common.ErrorResponse(c, 500, "新增失败!")
	} else {
		common.SuccessResponse(c, modelOid)
	}
}

// UpdateModelOid 更新ModelOID信息
// @Summary 更新ModelOID信息
// @Description 更新ModelOID信息
// @Tags ModelOID管理
// @Accept json
// @Produce json
// @Param updateData body map[string]interface{} true "更新数据，必须包含id字段"
// @Success 200 {object} common.Result "成功"
// @Failure 400 {object} common.Result "参数错误"
// @Failure 500 {object} common.Result "更新失败"
// @Router /api/modeloid/update [put]
func UpdateModelOid(c *gin.Context) {
	var updateData map[string]interface{}
	if err := c.ShouldBindJSON(&updateData); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "参数错误",
			"data":    nil,
		})
		return
	}

	id, ok := updateData["id"].(float64)
	if !ok {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "ID 参数错误",
			"data":    nil,
		})
		return
	}

	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	if err := db.Model(&entity.ModelOid{}).Where("id = ?", int(id)).Updates(updateData).Error; err != nil {
		common.ErrorResponse(c, 500, "更新失败!")
		return
	}

	common.SuccessResponse(c, nil)
}

// DeleteModelOid 删除ModelOID信息
// @Summary 删除ModelOID信息
// @Description 根据ID删除ModelOID信息
// @Tags ModelOID管理
// @Accept json
// @Produce json
// @Param id path string true "ModelOID信息ID"
// @Success 200 {object} common.Result "成功"
// @Failure 500 {object} common.Result "删除失败"
// @Router /api/modeloid/delete/{id} [delete]
func DeleteModelOid(c *gin.Context) {
	id := c.Param("id")

	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	if err := db.Delete(&entity.ModelOid{}, id).Error; err != nil {
		common.ErrorResponse(c, 500, "删除失败!")
		return
	}

	common.SuccessResponse(c, gin.H{})
}

// ExportModelOid 导出ModelOID数据为CSV
// @Summary 导出ModelOID数据
// @Description 导出ModelOID数据为CSV格式
// @Tags ModelOID管理
// @Accept json
// @Produce text/csv
// @Param model query string false "设备型号筛选"
// @Success 200 {file} file "CSV文件"
// @Failure 500 {object} common.Result "导出失败"
// @Router /api/modeloid/export [get]
func ExportModelOid(c *gin.Context) {
	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	// 获取查询参数
	model := c.Query("model")

	// 构建查询条件
	query := db.Model(&entity.ModelOid{})
	if model != "" {
		query = query.Where("model LIKE ?", "%"+model+"%")
	}

	// 获取所有数据
	var modelOids []entity.ModelOid
	if err := query.Find(&modelOids).Error; err != nil {
		common.ErrorResponse(c, 500, "查询数据失败")
		return
	}

	// 生成带时间戳的文件名
	timestamp := time.Now().Format("20060102_150405")
	filename := fmt.Sprintf("model_oid_export_%s.csv", timestamp)

	// 设置响应头
	c.Header("Content-Type", "text/csv; charset=utf-8")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))

	// 写入UTF-8 BOM头，解决中文乱码问题
	c.Writer.Write([]byte{0xEF, 0xBB, 0xBF})

	// 创建CSV写入器
	writer := csv.NewWriter(c.Writer)
	defer writer.Flush()

	// 写入CSV头部（使用中文标题）
	headers := []string{"ID", "设备型号", "OID名称", "OID值", "描述"}
	if err := writer.Write(headers); err != nil {
		logging.Errorf("写入CSV头部失败: %v", err)
		return
	}

	// 写入数据行
	for _, oid := range modelOids {
		record := []string{
			strconv.Itoa(oid.Id),
			oid.Model,
			oid.OidName,
			oid.OidValue,
			oid.Descr,
		}
		if err := writer.Write(record); err != nil {
			logging.Errorf("写入CSV数据失败: %v", err)
			return
		}
	}
}

// ImportModelOid 导入ModelOID数据从CSV
// @Summary 导入ModelOID数据
// @Description 从CSV文件导入ModelOID数据
// @Tags ModelOID管理
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "CSV文件"
// @Param replace_existing formData boolean false "是否替换已存在的数据"
// @Success 200 {object} common.Result{data=map[string]int} "导入成功"
// @Failure 400 {object} common.Result "参数错误"
// @Failure 500 {object} common.Result "导入失败"
// @Router /api/modeloid/import [post]
func ImportModelOid(c *gin.Context) {
	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	// 获取上传的文件
	file, _, err := c.Request.FormFile("file")
	if err != nil {
		common.ErrorResponse(c, 400, "文件上传失败: "+err.Error())
		return
	}
	defer file.Close()

	// 获取是否替换已存在数据的参数
	replaceExisting := c.PostForm("replace_existing") == "true"

	// 读取CSV数据
	reader := csv.NewReader(file)
	records, err := reader.ReadAll()
	if err != nil {
		common.ErrorResponse(c, 400, "CSV文件解析失败: "+err.Error())
		return
	}

	// 处理UTF-8 BOM，如果第一个字段包含BOM，需要去除
	if len(records) > 0 && len(records[0]) > 0 {
		firstField := records[0][0]
		// UTF-8 BOM 字符序列
		if strings.HasPrefix(firstField, "\uFEFF") {
			records[0][0] = strings.TrimPrefix(firstField, "\uFEFF")
		}
	}

	if len(records) < 2 {
		common.ErrorResponse(c, 400, "CSV文件格式错误，至少需要包含头部和一行数据")
		return
	}

	// 验证CSV头部格式（支持中英文两种格式）
	headers := records[0]
	expectedHeadersEn := []string{"ID", "Model", "OID Name", "OID Value", "Description"}
	expectedHeadersCn := []string{"ID", "设备型号", "OID名称", "OID值", "描述"}

	// 添加调试日志
	logging.Infof("CSV导入 - 实际头部: %v", headers)
	logging.Infof("CSV导入 - 期望英文头部: %v", expectedHeadersEn)
	logging.Infof("CSV导入 - 期望中文头部: %v", expectedHeadersCn)

	// 检查头部数量是否正确
	if len(headers) != 5 {
		common.ErrorResponse(c, 400, fmt.Sprintf("CSV头部列数错误，期望5列，实际%d列", len(headers)))
		return
	}

	// 检查是否匹配英文格式
	isEnglishFormat := true
	for i, header := range expectedHeadersEn {
		if strings.TrimSpace(headers[i]) != header {
			isEnglishFormat = false
			break
		}
	}

	// 检查是否匹配中文格式
	isChineseFormat := true
	for i, header := range expectedHeadersCn {
		if strings.TrimSpace(headers[i]) != header {
			isChineseFormat = false
			break
		}
	}

	// 如果两种格式都不匹配，返回错误
	if !isEnglishFormat && !isChineseFormat {
		// 输出实际的头部信息用于调试
		logging.Errorf("CSV头部格式错误，实际头部: %v", headers)
		common.ErrorResponse(c, 400, fmt.Sprintf("CSV头部格式错误，期望英文格式: %v 或中文格式: %v，实际: %v", expectedHeadersEn, expectedHeadersCn, headers))
		return
	}

	// 开始事务
	tx := db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	successCount := 0
	updateCount := 0
	skipCount := 0
	errorCount := 0

	// 处理数据行
	for i, record := range records[1:] {
		if len(record) < 5 {
			logging.Warnf("第%d行数据格式错误，跳过", i+2)
			errorCount++
			continue
		}

		modelOid := entity.ModelOid{
			Model:    strings.TrimSpace(record[1]),
			OidName:  strings.TrimSpace(record[2]),
			OidValue: strings.TrimSpace(record[3]),
			Descr:    strings.TrimSpace(record[4]),
		}

		// 检查是否已存在相同的记录（根据Model和OidName判断）
		var existingOid entity.ModelOid
		err := tx.Where("model = ? AND oid_name = ?", modelOid.Model, modelOid.OidName).First(&existingOid).Error

		if err == nil {
			// 记录已存在
			if replaceExisting {
				// 更新现有记录
				if err := tx.Model(&existingOid).Updates(modelOid).Error; err != nil {
					logging.Errorf("更新第%d行数据失败: %v", i+2, err)
					errorCount++
				} else {
					updateCount++
				}
			} else {
				skipCount++
			}
		} else {
			// 新增记录
			if err := tx.Create(&modelOid).Error; err != nil {
				logging.Errorf("插入第%d行数据失败: %v", i+2, err)
				errorCount++
			} else {
				successCount++
			}
		}
	}

	if errorCount > 0 {
		tx.Rollback()
		common.ErrorResponse(c, 500, fmt.Sprintf("导入失败，有%d条记录出错", errorCount))
		return
	}

	tx.Commit()

	result := map[string]int{
		"success_count": successCount,
		"update_count":  updateCount,
		"skip_count":    skipCount,
		"total_count":   len(records) - 1,
	}

	logging.Infof("ModelOID导入完成，新增: %d, 更新: %d, 跳过: %d", successCount, updateCount, skipCount)
	common.SuccessResponse(c, result)
}

// GetModelOidModels 获取所有ModelOID中的Model列表
// @Summary 获取ModelOID中的Model列表
// @Description 获取所有不重复的Model列表（从ModelOID表中查询）
// @Tags ModelOID管理
// @Accept json
// @Produce json
// @Success 200 {object} common.Result{data=[]string} "成功"
// @Failure 500 {object} common.Result "失败"
// @Router /api/modeloid/models [get]
func GetModelOidModels(c *gin.Context) {
	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	var models []string
	if err := db.Model(&entity.ModelOid{}).Distinct("model").Pluck("model", &models).Error; err != nil {
		common.ErrorResponse(c, 500, "查询失败")
		return
	}

	common.SuccessResponse(c, models)
}

// DebugCSVFormat 调试CSV格式（临时接口，用于测试）
// @Summary 调试CSV格式
// @Description 上传CSV文件查看解析结果，不实际导入数据
// @Tags ModelOID管理
// @Accept multipart/form-data
// @Produce json
// @Param file formData file true "CSV文件"
// @Success 200 {object} common.Result "解析成功"
// @Failure 400 {object} common.Result "解析失败"
// @Router /api/modeloid/debug-csv [post]
func DebugCSVFormat(c *gin.Context) {
	// 获取上传的文件
	file, _, err := c.Request.FormFile("file")
	if err != nil {
		common.ErrorResponse(c, 400, "文件上传失败: "+err.Error())
		return
	}
	defer file.Close()

	// 读取CSV数据
	reader := csv.NewReader(file)
	records, err := reader.ReadAll()
	if err != nil {
		common.ErrorResponse(c, 400, "CSV文件解析失败: "+err.Error())
		return
	}

	// 处理UTF-8 BOM
	if len(records) > 0 && len(records[0]) > 0 {
		firstField := records[0][0]
		// UTF-8 BOM 字符序列
		if strings.HasPrefix(firstField, "\uFEFF") {
			records[0][0] = strings.TrimPrefix(firstField, "\uFEFF")
		}
	}

	result := map[string]interface{}{
		"total_rows":     len(records),
		"headers":        records[0],
		"first_data_row": nil,
	}

	if len(records) > 1 {
		result["first_data_row"] = records[1]
	}

	// 检查头部格式
	if len(records) > 0 {
		headers := records[0]
		expectedHeadersEn := []string{"ID", "Model", "OID Name", "OID Value", "Description"}
		expectedHeadersCn := []string{"ID", "设备型号", "OID名称", "OID值", "描述"}

		isEnglishFormat := true
		for i, header := range expectedHeadersEn {
			if i >= len(headers) || strings.TrimSpace(headers[i]) != header {
				isEnglishFormat = false
				break
			}
		}

		isChineseFormat := true
		for i, header := range expectedHeadersCn {
			if i >= len(headers) || strings.TrimSpace(headers[i]) != header {
				isChineseFormat = false
				break
			}
		}

		result["is_english_format"] = isEnglishFormat
		result["is_chinese_format"] = isChineseFormat
		result["expected_english"] = expectedHeadersEn
		result["expected_chinese"] = expectedHeadersCn
	}

	common.SuccessResponse(c, result)
}
